﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Helpers;

namespace Budgeter.ViewModels.Budget.CreateOrEdit
{

    public class Loader : ILoader<Models.Budget, ViewModel>
    {
        public ViewModel Load(Models.BudgeterContext db, Models.Budget from)
        {
            ViewModel vm = new ViewModel
            {
                BudgetId = from.BudgetId,
                Entries = BuildEntries(db, from.Entries),
                IntervalId = from.Interval == null ? 0 : from.Interval.IntervalId,
                ReceiptNumber = from.ReceiptNumber,
            };
            PopulateDataForView(db, vm);
            return vm;
        }

        public void PopulateDataForView(Models.BudgeterContext db, ViewModel model)
        {
            model.AllIntervals = db.Intervals;
            model.IntervalsAsJson = Json.Encode(Budgeter.ViewModels.ViewModelHelpers.ToIdIndexedArray(model.AllIntervals, x => x.IntervalId));
        }

        private static IEnumerable<ViewModel.Entry> BuildEntries(Models.BudgeterContext db, IEnumerable<Models.Entry> fromEntries)
        {
            // Method:
            //  1) build a list of all entries, one for each entry type defined in the database.
            //  2) transform all entries from the model
            //  3) merge the two lists, preferring entries from step 2

            // A _db.EntryTypes.AsEnumerable() call here was required to disconnect the query from L2E and instead use L2O, in
            //  order to get around an "Only parameterless constructors and initializers are supported 
            //  in LINQ to Entities" exception which I didn't fully understand :/
            //  Update: turns out it was due to the model having a SelectLists in it, which has no parameterless
            //  constructor.  I removed the SelectLists for other reasons (can not be bound to actions), so
            //  this is no longer relevant.  I've left the comment here for posterity though!

            var allEntries = from et in db.EntryTypes
                             select new ViewModel.Entry
                             {
                                 Amount = 0,
                                 Category = et.Category,
                                 IsIncome = et.IsIncome,
                                 Name = et.Name,
                             };
            var modelEntries = from e in fromEntries
                               select new ViewModel.Entry
                               {
                                   Amount = e.Amount,
                                   Category = e.EntryType.Category,
                                   IntervalId = e.Interval == null ? 0 : e.Interval.IntervalId,
                                   IsIncome = e.EntryType.IsIncome,
                                   Name = e.EntryType.Name,
                               };
            return modelEntries.Union(allEntries).ToArray();
        }

    }

}